//
//  HttpRequestManager.m
//  HttpLibraries
//
//  Created by admin on 2018/10/11.
//  Copyright © 2018年 admin. All rights reserved.
//

#import "HttpRequestManager.h"
#import "HttpResponse.h"
#import <AFNetworking/AFNetworking.h>
#import <YYModel/YYModel.h>

@interface HttpRequestManager ()

@property (nonatomic, strong) AFHTTPSessionManager *manager;

@end

@implementation HttpRequestManager

- (id)init{
    if (self = [super init]){
        [self initManager];
    }
    return self;
}


- (void)initManager{
    
    AFHTTPSessionManager* _manager = [AFHTTPSessionManager manager];
    
    ///config
    NSURLSessionConfiguration* _config = _manager.session.configuration;
    _config.timeoutIntervalForRequest = 10.f;
    _config.timeoutIntervalForResource = 10.f;
    _config.requestCachePolicy  = NSURLRequestReturnCacheDataElseLoad;
    _config.HTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    
    ///request
    
    AFJSONRequestSerializer* requestSerializer = [AFJSONRequestSerializer serializer];
    _manager.requestSerializer = requestSerializer;
    
    ///response
    AFJSONResponseSerializer* responseSerializer = [AFJSONResponseSerializer serializer];
    responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"text/plain", @"image/jpeg", nil];
    _manager.responseSerializer = responseSerializer;
    
    
    ///securityPolicy
    AFSecurityPolicy* securityPolicy = [AFSecurityPolicy defaultPolicy];
    securityPolicy.allowInvalidCertificates = YES;
    securityPolicy.validatesDomainName = NO;
    _manager.securityPolicy = securityPolicy;
    
    self.manager = _manager;
}

#pragma mark -------------------- public --------------------

+ (instancetype)sharedInstance
{
    static HttpRequestManager *instance = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (void)setRequestHeader:(NSDictionary *)requestHeader{

    if(requestHeader.count){
        [requestHeader enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [self.manager.requestSerializer setValue:obj forHTTPHeaderField:key];
        }];
    }
}


- (void)upload:(NSString *)url params:(NSDictionary *)params fileConfigs:(NSArray<HttpUploadFile *> *)fileConfigs response:(Class)responseClass callback:(HttpResponseBlock)callback{
    
    [self.manager POST:url parameters:params headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        if (fileConfigs){
            for (int i = 0; i < [fileConfigs count]; i ++)
            {
                HttpUploadFile *fileConfig = [fileConfigs objectAtIndex:i];
                [formData appendPartWithFileData:fileConfig.fileData name:fileConfig.name fileName:fileConfig.fileName mimeType:fileConfig.mimeType];
            }
        }
        
    } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
#ifdef DEBUG
        NSLog(@"request:%@->response:%@", url, responseObject);
#endif
        
        HttpResponse* responseObj = [HttpResponse yy_modelWithJSON:responseObject];
        if(responseClass){
            id data = responseObject[@"data"];
            if([data isKindOfClass:[NSArray class]]){
                responseObj.data = [NSArray yy_modelArrayWithClass:responseClass json:data];
            }else{
                responseObj.data = [responseClass yy_modelWithJSON:data];
            }
        }
        if (callback){
            callback(responseObj);
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        HttpResponse* response = [HttpResponse new];
        response.code = error.code;
        response.message = @"请求失败，请稍后重试";
        response.data = nil;
        if (callback){
            callback(response);
        }
    }];
}

-(void)requestWithURL:(NSString *)url method:(HttpMethod)method params:(NSDictionary *)params response:(Class)responseClass callback:(HttpResponseBlock)callback{
    
    [self callWithURL:url method:method params:params success:^(id response) {
#ifdef DEBUG
        NSLog(@"request:%@->response:%@", url, response);
#endif
        HttpResponse* responseObj = [HttpResponse yy_modelWithJSON:response];
        if(responseClass){
            id data = response[@"data"];
            if([data isKindOfClass:[NSArray class]]){
                responseObj.data = [NSArray yy_modelArrayWithClass:responseClass json:data];
            }else{
                responseObj.data = [responseClass yy_modelWithJSON:data];
            }
        }
        if (callback){
            callback(responseObj);
        }

    } failure:^(NSError *error) {
        
        HttpResponse* response = [HttpResponse new];
        response.code = error.code;
        response.message = @"请求失败，请稍后重试";
        response.data = nil;
        if (callback){
            callback(response);
        }
    }];
}


- (void)callWithURL:(NSString *)url method:(HttpMethod)method params:(NSDictionary *)params success:(void(^)(id response))success failure:(void(^)(NSError* error))failure{
    switch (method)
    {
        case HttpMethodGET:
        {
            [self get:url params:params success:success failure:failure];
        }
            break;
        case HttpMethodPOST:
        {
            [self post:url params:params success:success failure:failure];
        }
            break;
        case HttpMethodPUT:
        {
            [self put:url params:params success:success failure:failure];
        }
            break;
        case HttpMethodDELETE:
        {
            [self deleteWithUrl:url params:params success:success failure:failure];
        }
            break;
        default:
            break;
    }
}

- (void)requestCookie:(NSString *) url callback:(HttpResponseBlock)callback{
    self.manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    [self.manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSString* cookieStr = [self getCookieByHttpRequest:task];
        HttpResponse* reponse = [HttpResponse new];
        reponse.code = 0;
        reponse.data = cookieStr;
        if (callback) {
            callback(reponse);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
       //获取 Cookie
       //NSString * cookieStr = [self getCookieByHttpRequest:task];
       HttpResponse* reponse = [HttpResponse new];
       if (callback) {
          callback(reponse.failureDefalut);
       }
    }];
}


- (NSString*)getCookieByHttpRequest:(NSURLSessionDataTask * _Nullable) task{
    NSMutableString* cookieStr = [[NSMutableString alloc]init];
    
    //方法一
    if (task != nil) {
        NSHTTPURLResponse* response = (NSHTTPURLResponse* )task.response;
        NSDictionary *allHeaderFieldsDic = response.allHeaderFields;
        NSString *setCookie = allHeaderFieldsDic[@"Set-Cookie"];
        if (setCookie != nil) {
            NSString *cookie = [[setCookie componentsSeparatedByString:@";"] objectAtIndex:0];
            [cookieStr appendString:cookie];
            NSLog(@"cookie －> %@", cookieStr);
        }
    }
    
    //如果通过方法一获取失败，尝试使用方法二
    if (cookieStr.length == 0) {
        NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
        NSArray *cookieArr = [cookieJar cookies];
        for(NSHTTPCookie *cookie in cookieArr) {
            [cookieStr appendString:cookie.name];
            [cookieStr appendString:@"="];
            [cookieStr appendString:cookie.value];
            [cookieStr appendString:@","];
        }
        [cookieStr deleteCharactersInRange:NSMakeRange(cookieStr.length-1, 1)];
        NSLog(@"cookie => %@", cookieStr);
    }
    
    return cookieStr;
}

- (void)saveCookie:(NSString*) cookie {
    [[NSUserDefaults standardUserDefaults] setObject:cookie forKey:@"key_cookie"];
}


- (void)getCookieByCache {
    [[NSUserDefaults standardUserDefaults] stringForKey:@"key_cookie"];
}

- (void)removeCookie {
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"key_cookie"];
}

#pragma mark -------------------- private --------------------



- (void)get:(NSString *)url params:(NSDictionary *)params success:(void(^)(id response))success failure:(void(^)(NSError* error))failure{
    
    [self.manager GET:url parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if(success){
            success(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        if(failure){
            failure(error);
        }
    }];
}

- (void)post:(NSString *)url params:(NSDictionary *)params success:(void(^)(id response))success failure:(void(^)(NSError* error))failure{
    
    [self.manager POST:url parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if(success){
            success(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if(failure){
            failure(error);
        }
    }];
}

- (void)put:(NSString *)url params:(NSDictionary *)params success:(void(^)(id response))success failure:(void(^)(NSError* error))failure{
    
    [self.manager PUT:url parameters:params headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if(success){
            success(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if(failure){
            failure(error);
        }
    }];
}

- (void)deleteWithUrl:(NSString *)url params:(NSDictionary *)params success:(void(^)(id response))success failure:(void(^)(NSError* error))failure{
    
    [self.manager DELETE:url parameters:params headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if(success){
            success(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if(failure){
            failure(error);
        }
    }];
}


- (void)cancelAllOperations
{
    [self.manager.operationQueue cancelAllOperations];
}

@end
